/**
 * 数据表配置文件解析类
 */
package cn.antia.cwin;

import java.util.*;

import org.dom4j.*;
import org.dom4j.io.SAXReader;

import cn.antia.cwin.db.DbService;
import cn.antia.cep.common.*;

/**
 * @author sunkeei
 * @date 2007-11-13
 * @version 0.1
 * @time 
 */

public class DBConfiger {
	private static Document doc;
	
	static{
		reset();
	}
	public DBConfiger(){
	}
	
	/**
	 * 重置
	 */
	public static void reset(){
		SAXReader reader = new SAXReader();
		try{
			doc = reader.read(SysConf.SYSTEM_DB_CONFIG);
		}catch(DocumentException de){
			AntiaLog.fatal("DBConfiger reset error.");
			de.printStackTrace();
		}
	}
    
    public static Map<String, Cele> getCommonFields() {
        Map<String, Cele> commonFields = new HashMap<String, Cele>();
        Element element;
		String path;
        path = "/all-table/common/field";
        List eles = doc.selectNodes(path);
        if (eles != null && eles.size() > 0) {
            for (Object ele : eles) {
                element = (Element) ele;
                Cele cele = new Cele();
                setAttribute(cele, "_COMMON_", element, ConfigConst.FORM_TABLE);
                commonFields.put(cele.getField().getFieldName(), cele);
            }
        }
        return commonFields;
    }
    
    /**
	 * 返回这一个表的所有元素
	 * @param table table
	 * @return emements 
	 */
	public static List<Cele> getTableElements(String table) {
        List<Cele> list = ConfigPoolHelper.getDbElements(table);
        Element element;
        String path;
        for (Cele ec : list) {
            path = new StringBuffer("/all-table/table[@id='").append(table).append("']/field[@name='").append(ec.getField().getFieldName()).append("']").toString();
            element = (Element) doc.selectSingleNode(path);
            setAttribute(ec, table, element, ConfigConst.FORM_TABLE);
        }
        return list;
    }
	/**
	 * 返回这个表的显示列数
	 *
     * @param table 显示列数
     * @return 默认为2*/
	public static String getDispColumn(String table){
		String path = new StringBuffer("/all-table/table[@id='").append(table).append("']/dispcol").toString();
		Element ele = (Element)doc.selectSingleNode(path);
		if(ele != null){
			String cols = ele.attributeValue("cols");
			return cols == null ? "2" : cols;
		}
		return "2";
	}
    
	/***
	 * 设置其它的属性
	 * @param table 表
	 * @param cele	ElementComsat,刚读取数据库属性的ElementComsat
	 * @param element XML Element
	 * @param from 调用的来源，以便于报告错误信息
	 * @return ElementComsat
	 */
	public static Cele setAttribute(Cele cele,String table,Element element,String from) {
		if(element == null){
			AntiaLog.fatal("数据库配置错误：表：" + table + " 字段：" + cele.getField().getFieldName());
			return cele;
		}
		//查看是否需要引用了其它字段，如果引用了，则不分析
		String ref;			//字段引用则不分析
		String[] table_field;	//表与字段
		//是否有引用属性
        ref = element.attributeValue("ref");
        if(ref != null && ref.trim().length() > 0) {
            if (ref.indexOf(".") > 0) {
                table_field = ref.split("\\.");
                if (table_field.length != 2) {
                    AntiaLog.error(from + " " + table_field[0] + "condition config error.");
                }
                cele = ConfigPoolHelper.getElementComsat(table_field[0], table_field[1]);
                if (cele == null) {
                    AntiaLog.error(from + " " + table_field[0] + " condition not found:" + table_field[0] + ":" + table_field[1]);
                }
            }else {
                cele = ConfigPoolHelper.getCommonField(ref);
                updateCele(ConfigPoolHelper.getDBCele(table,cele.getField().getFieldName()),cele);
            }
            if (cele != null) {
                cele = cele.clone();
                cele.setOwner(table);
            }
        }
		boolean isNew = false;
		if(cele == null || cele.getField().getFieldName() == null){
			cele = new Cele();
			isNew = true;
		}
		//取得属性列表
		Attribute attr;
		String an,av;		//属性名与属性值
        DBField field = cele.getField();
        for(Iterator i = element.attributeIterator();i.hasNext();){
			attr = (Attribute)i.next();
			an = attr.getName();
			av = attr.getValue();
			//name,default,nullable,length,isKey,modifyDefault,validType,decLen,general,min.max
			if(an.equals("default")){
				field.setDefault(av);
			}else if(an.equals("nullable")){
				if(field.getAllowNull() == null || field.getAllowNull()){
					field.setAllowNull(Boolean.valueOf(av));
				}
			}else if(an.equals("maxLen")){
				//不能大过DB规定的长度
				if(field.getMaxLen() == null || field.getMaxLen() > Integer.parseInt(av)){
					field.setMaxLen(Integer.valueOf(av));
				}
			}else if(an.equals("minLen")){
				field.setMinLen(Integer.valueOf(av));
			}else if(an.equals("modifyValue")){
				field.setModifyValue(av);
			}else if(an.equals("validType")){
				field.setValidType(av);
			}else if(an.equals("desLen")){
				field.setDecLen(Integer.valueOf(av));
			}else if(an.equals("general")){
				field.setGeneral(!av.equals("false"));
			}else if(an.equals("min")){
				//不能小于DB所规定的最小值
				if(field.getMin() == null || field.getMin() < Integer.parseInt(av)){
					field.setMin(Integer.valueOf(av));
				}
			}else if(an.equals("max")){
				//不能大于DB规定的最大值
				if(field.getMax() == null || field.getMax() > Integer.parseInt(av)){
					field.setMax(Integer.valueOf(av));
				}
			}else if(an.equals("encrypt")){
				cele.getHtmlWidget().setAttr("readonly","true");
			}else if(isNew && an.equals("name")){
				//如果是新的ElementComsat并且是名称属性，则设置
				field.setFieldName(av);
			}else if (an.equalsIgnoreCase("des")) {
                field.setDes(av);
            }else if (an.equalsIgnoreCase("order")) {
                field.setOrder("true".equalsIgnoreCase(av));
            }else if (an.equalsIgnoreCase("cond")) {
                field.setCond("true".equalsIgnoreCase(av));
            }else if (!an.equals("name") && !an.equals("isKey") && !an.equals("ref")) {
                AntiaLog.error(from + " " + table + ": Field:" + field.getFieldName() + " 's Attr " + an + " is not required.");
            }
		}
		//检查表现形式(INPUT/TD/COMMENT)
		Element ele;
        HtmlWidget hw = cele.getHtmlWidget();
        if (hw == null) {
            hw = new HtmlWidget();
            cele.setHtmlWidget(hw);
        }
        for( Iterator it = element.elementIterator();it.hasNext();){
			ele = (Element)it.next();
			String eleName = ele.getName();
			//input 属性设置
			if(eleName.equals("input")){
				for(Iterator it2 = ele.attributeIterator();it2.hasNext();){
					attr = (Attribute)it2.next();
					an = attr.getName();
					av = attr.getValue();
					if(an.equals("type")){
						hw.setHtmlType(checkHtmlType(av) ? av : "text");
					}else if(an.equals("des")){
						hw.setDispText(av);
					}else if(!an.equals("double")){
                        hw.setAttr(an,av);
                        AntiaLog.debug(from + " " + table + ": Field:" + cele.getField().getFieldName() + " 's HTML INPUT Attr " + an + " was setted.");
					}
				}
                //default input type
                if(hw.getHtmlType() == null){
					hw.setHtmlType("text");
				}
                //default description
                if (hw.getDispText() == null) {
                    hw.setDispText(cele.getField().getDes());
                }
                //如果这个类型是下拉列表，则给他以值
				if(hw.getHtmlType().equals("select") || hw.getHtmlType().equals("checkbox") || hw.getHtmlType().equals("radio")){
					//取值
					Element options = ele.element("options");
					hw.setOptions(getDropList(options));
				}
			}else if(eleName.equals("output")){
				Output td = new Output();
				td.setDispMode(ele.attributeValue("dispMode"));
				td.setText(ele.attributeValue("des") == null ? hw.getDispText() : ele.attributeValue("des"));
				td.setGoat(ele.attributeValue("goat"));
				td.setLinkUrl(ele.attributeValue("linkUrl"));
				td.setOnclick(ele.attributeValue("onClick"));
				td.setTitle(ele.attributeValue("title"));
				td.setWidth(ele.attributeValue("width"));
                td.setDispType(ele.attributeValue("dispType"));
                if(isHiddenDisp(td.getDispMode())){
					if(td.getGoat() == null){
						td.setGoat(ConfigConst.DEFAULT_GOAT_STRING);
					}
				}
				cele.setTd(td);
			}else if(eleName.equals("comment")){
				hw.setComment(ele.getText());
			}else if (eleName.equalsIgnoreCase("options")) {
                //取值
                cele.setOptions(getDropList(ele.element("options")));
                if(hw.getHtmlType().equals("select") || hw.getHtmlType().equals("checkbox") || hw.getHtmlType().equals("radio")){
                    hw.setOptions(cele.getOptions());
                }
            }
		}
		//设置TD属性
		if(cele.getTd() == null){
			Output td = new Output();
			td.setText(hw.getDispText());
			td.setField(cele.getField().getFieldName());
			cele.setTd(td);
		}else if(cele.getTd().getField() == null){
			cele.getTd().setField(cele.getField().getFieldName());
		}
		Cele.setValitionString(cele);
		return cele;
	}
	/**
	 * 返回下拉列表 以TreeMap形式存储
	 * @param options options
	 * @return Map<String,String>
	 */
	public static Map<String,String> getDropList(Element options){
        Map<String,String> map;
		String name;
		String value;
		//如果三个属性都有
        String sql = options.getTextTrim();
        if(sql != null && sql.length() > 10){
            map = new DbService().queryMap(sql);
            if (map == null || map.size() < 1) {
                AntiaLog.error(": Field: HTML options attr option must set name and value attribute.");
            }
            return map;
		}else{
			//如果不从数据库查询,查询以下的 option
			Element option;
			map = new TreeMap<String,String>();
			for(Iterator it = options.elementIterator("option");it.hasNext();){
				option = (Element)it.next();
				name = option.valueOf("@des");
				value = option.valueOf("@val");
				if(name != null && value != null){
					map.put(value, name);
				}else{
					AntiaLog.error(": Field: HTML options attr option must set name and value attribute.");
				}
			}
			return map;
		}
	}
	


    /**
     * 更新另一个CELE
     * @param old   原来的
     * @param newc  新的 newc 将覆盖 old
     * @return Cele
     */
    public static Cele updateCele(Cele old,Cele newc) {
        if (old == null) {
            return newc;
        }
        //Field
        DBField ofield = old.getField();
        DBField nfield = newc.getField();
        ofield.setDefault(nfield.getDefault() != null ? nfield.getDefault() : ofield.getDefault());
        ofield.setGeneral(nfield.isGeneral() ? nfield.isGeneral() : ofield.isGeneral());
        ofield.setDecLen(nfield.getDecLen() != null ? nfield.getDecLen() : ofield.getDecLen());
        ofield.setAllowNull(nfield.getAllowNull() != null ? nfield.getAllowNull() : ofield.getAllowNull());
        ofield.setMax(nfield.getMax() != null ? nfield.getMax() : ofield.getMax());
        ofield.setMaxLen(nfield.getMaxLen() != null ? nfield.getMaxLen() : ofield.getMaxLen());
        ofield.setMin(nfield.getMin() != null ? nfield.getMin() : ofield.getMin());
        ofield.setMinLen(nfield.getMinLen() != null ? nfield.getMinLen() : ofield.getMinLen());
        ofield.setModifyValue(nfield.getModifyValue() != null ? nfield.getModifyValue() : ofield.getModifyValue());
        ofield.setValidType(nfield.getValidType() != null ? nfield.getValidType() : ofield.getValidType());
        ofield.setCond(nfield.isCond() ? nfield.isCond() : ofield.isCond());
        ofield.setOrder(nfield.isOrder() ? nfield.isOrder() : ofield.isOrder());
        old.setField(ofield);
        //html widget
        HtmlWidget ohw = old.getHtmlWidget();
        HtmlWidget nhw = newc.getHtmlWidget();
        ohw.setComment(nhw.getComment() != null ? nhw.getComment() : ohw.getComment());
        ohw.setDispText(nhw.getDispText() != null ? nhw.getDispText() : ohw.getDispText());
        ohw.setHtmlType(nhw.getHtmlType() != null ? nhw.getHtmlType() : ohw.getHtmlType());
        ohw.setIndex(nhw.getIndex() != null ? nhw.getIndex() : ohw.getIndex());
        ohw.setOptions(nhw.getOptions() != null ? nhw.getOptions() : ohw.getOptions());
        //attris
        Map<String,String> attrs = nhw.getAttrs();
        if (ohw.getAttrs() == null) {
            ohw.setAttrs(attrs);
        }else if (attrs != null && attrs.size() > 0) {
            Map<String, String> oattrs = ohw.getAttrs();
            for (Map.Entry<String, String> entry:attrs.entrySet()) {
                oattrs.put(entry.getKey(), entry.getValue());
            }
            ohw.setAttrs(oattrs);
        }
        old.setHtmlWidget(ohw);
        //td
        Output otd = old.getTd();
        Output ntd = newc.getTd();
        otd.setDispMode(ntd.getDispMode() != null ? ntd.getDispMode() : otd.getDispMode());
        otd.setGoat(ntd.getGoat() != null ? ntd.getGoat() : otd.getGoat());
        otd.setLinkUrl(ntd.getLinkUrl() != null ? ntd.getLinkUrl() : otd.getLinkUrl());
        otd.setOnclick(ntd.getOnclick() != null ? ntd.getOnclick() : otd.getOnclick());
        otd.setText(ntd.getText() != null ? ntd.getText() : otd.getText());
        otd.setTitle(ntd.getTitle() != null ? ntd.getTitle() : otd.getTitle());
        otd.setWidth(ntd.getWidth() != null ? ntd.getWidth() : otd.getWidth());
        old.setTd(otd);
        //options
        old.setOptions(newc.getOptions() != null ? newc.getOptions() : old.getOptions());
        return newc;
    }

    public static boolean isHiddenDisp(String dispMode){
        return dispMode != null && (dispMode.equals("hidden") || dispMode.equals("hiddendiv") || dispMode.equals("pop"));
    }

    /**
	 * 检查HTML控件有有效性
	 * 这里的有效控件是指可以录入数据的HTML控件
	 * @param type  控件类型
     * @return HTML控件类型量否存在
     */
	public static boolean checkHtmlType(String type){
		String[] types = new String[]{"text","checkbox","select","radio","textarea","password","hidden","fckeditor"};
        for (String type1 : types) {
            if (type.equalsIgnoreCase(type1)) {
                return true;
            }
        }
        return false;
	}
}